/* ConsoleView
Michael Zahniser, 01/07/08

Header file for the ConsoleView class, which defines an SDL View where the
user can type in text and get responses back.
*/

#ifndef __MZ_CONSOLE_VIEW_H__
#define __MZ_CONSOLE_VIEW_H__

#include "View.h"
#include "Font.h"
#include "_common/Callback.h"

#include <list>
#include <string>
#include <utility>

using std::list;
using std::string;
using std::pair;



class ConsoleView : public View {
public:
	typedef CallbackT<const string &> Callback;


public:
	ConsoleView();

	void SetCallback(Callback &callback);
	void SetQueryColor(int red, int green, int blue);
	void SetResponseColor(int red, int green, int blue);
	void SetLineHeight(int height);
	void SetQueryIndent(int indent);
	void SetResponseIndent(int indent);

	// Display a response in the console.
	void PostResponse(const string &text);


protected:
	// Initialize a view, given the command line arguments for the program.
	// If the view cannot be initialized, this function should return false.
	// NOTE: SDL may not be initialized yet when a View's constructor is called,
	// so all initialization using SDL should be done here instead.
	virtual bool Initialize(const Surface &surface);

	// Handle an event. If the event involves (x, y) coordinates, they have been
	// translated such that (0, 0) is the top left corner of this View.
	// This function should return false if this view does not support the given
	// event and wants other views to have a chance to handle it.
	virtual bool Handle(const SDL_Event &event);

	// Draw the view in the given surface. The surface is passed as a (shallow)
	// copy so that it is impossible for derived classes to modify View::surface
	// to point to anything other than what Interface assigns to it.
	virtual void Draw(Surface surface) const;


private:
	class Entry {
	public:
		Entry() : isResponse(false) {}
		Entry(const string &text, bool isResponse = true)
			: text(text), isResponse(isResponse) {}

		string text;
		bool isResponse;
	};


private:
	string &Text();
	const string &Text() const;

	void NewLine();


private:
	Font queryFont;
	Font responseFont;
	// This is the height of one line of text.
	int lineHeight;
	// This is how much to indent queries and responses.
	int queryIndent;
	int responseIndent;
	// This is how far up we've scrolled, in lines.
	int scroll;

	Callback *callback;

	// This is a list of commands and responses.
	list<Entry> lines;

	int cursor;
	list<Entry>::const_iterator history;


private:
	static const int LINE_HEIGHT_PAD = 2;
	static const int QUERY_INDENT = 4;
	static const int RESPONSE_INDENT = 36;
};

#endif
